package com.xbsg.protocol.xf.server.netty;


import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xbsg.protocol.xf.RS485Util;
import com.xbsg.protocol.xf.constant.CtlStatus;
import com.xbsg.protocol.xf.constant.DataFlag;
import com.xbsg.protocol.xf.entiy.AppDataUtil;
import com.xbsg.protocol.xf.entiy.FireUploadData;
import com.xbsg.protocol.xf.entiy.FireUploadDataOboject;
import com.xbsg.protocol.xf.entiy.Protocol;
import com.xbsg.protocol.xf.server.HexEcodeUtil;
import com.xbsg.protocol.xf.service.FireUploadDataServiceImpl;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
@ChannelHandler.Sharable
class MyServerHandler extends ChannelInboundHandlerAdapter {
//    @Autowired
//    private MqttGateway mqttGateway;

    public static MyServerHandler myServerHandler;

    @Autowired
    private FireUploadDataServiceImpl fireUploadDataService;

    //2.初始化构造方法一定要有
    public MyServerHandler(){

    }
    //3.容器初始化的时候进行执行-这里是重点
    @PostConstruct
    public void init() {
        myServerHandler = this;
        myServerHandler.fireUploadDataService = this.fireUploadDataService;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        if(msg == null){
            return;
        }
        //获取客户端发送过来的消息
        ByteBuf byteBuf = (ByteBuf) msg;
        byte[] bytes = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(bytes);
        this.handlerMessage1(bytes);
    }


    private void handlerMessage1(byte[] message) {
        String resultTemp = RS485Util.covertHex2Ten(HexEcodeUtil.ByteArrayToHexStr(message));
        log.info("收到10进制字符串： " + resultTemp);
        if (CtlStatus.getCtl(message) == CtlStatus.UP) {
            log.info("控制单元命令字节" + DataUtil.bytes2String(CtlStatus.getCtl(message)) + "，开始解析");
            if(DataFlag.getDataFlag(message) == DataFlag.HEART_BEAT){
                log.info("通信线路上行测试");
            }else if(DataFlag.getDataFlag(message) == DataFlag.PART_STATUS){
                log.info("上传火灾自动报警系统部件运行状态");
            }else if(DataFlag.getDataFlag(message) == DataFlag.DEV_OPT){
                log.info("上传火灾自动报警系统设备操作信息");
            }else {
                log.warn("数据单元类型标志位是：" + DataFlag.getDataFlag(message) +"无法解析");
                return;
            }
        } else {
            log.warn("控制单元命令字节" + DataUtil.bytes2String(CtlStatus.getCtl(message)) + "，不是2暂时无法解析");
            return;
        }
        //DataUtil.bytes2String(message[26]).equals("2") ,控制位2

        //解析 FireUploadData
        FireUploadData fireUploadData = new FireUploadData();
        //fireUploadData.setId();
        fireUploadData.setBusSerialNum(DataUtil.bytes2String(message[3], message[2]));
        fireUploadData.setProtocolVersion(DataUtil.bytes2String(message[5],message[4]));
        fireUploadData.setTimeLable(DataUtil.bytes2String(message[11], message[10], message[9], message[8], message[7], message[6]));
        fireUploadData.setSourceAddress(DataUtil.bytes2String(message[17], message[16], message[15], message[14], message[13], message[12]));
        fireUploadData.setTargetAddress(DataUtil.bytes2String(message[23], message[22], message[21], message[20], message[19], message[18]));
        fireUploadData.setAppDataLength(DataUtil.bytes2String(message[25], message[24]));
        fireUploadData.setControl(DataUtil.bytes2String(message[26]));

        fireUploadData.setCheckSum(DataUtil.bytes2String(message[message.length - 3]));

        //发送数据
        //上报信息
        fireUploadData.setAppDataFlag(DataUtil.bytes2String(DataFlag.getDataFlag(message)));
        String appDataFlag= AppDataUtil.data_flag_map.get(fireUploadData.getAppDataFlag());
        if(!StringUtils.isEmpty(appDataFlag)){
            fireUploadData.setAppDataFlag(appDataFlag);
        }

        fireUploadData.setAppDataNum(DataUtil.bytes2String(message[28]));
        //应用数据单元长度
        int size = Integer.parseInt(fireUploadData.getAppDataNum());
        if (size > 0) {
            List<FireUploadDataOboject> fireUploadDataObojects = new ArrayList<FireUploadDataOboject>(size);
            //部件运行状态,信息体44个字节，时间标签6个字节
            if (DataFlag.getDataFlag(message) == DataFlag.PART_STATUS) {
                for (int j = 0; j < size; j++) {
                    //part_status
                    int offset = j * 50;
                    FireUploadDataOboject object = new FireUploadDataOboject();
                    object.setDeviceType(DataUtil.bytes2String(message[29 + offset]));
                    String value2 = AppDataUtil.device_type_map.get(object.getDeviceType());
                    if(!StringUtils.isEmpty(value2)){
                        object.setDeviceType(value2);
                    }

                    object.setDeviceAddress(DataUtil.bytes2String(message[30 + offset]));
                    object.setPartType(DataUtil.bytes2String(message[31 + offset]));
                    String value1 = AppDataUtil.part_type_map.get(object.getPartType());
                    if(!StringUtils.isEmpty(value1)){
                        object.setPartType(value1);
                    }
                    //asii ,8
                    object.setPartAddress(DataUtil.get_part_address(message, 32 + offset, 8));
                    object.setPartStatus(DataUtil.bytes2String(message[40 + offset]));
                    String value = AppDataUtil.device_part_status_map.get(object.getPartStatus());
                    if(!StringUtils.isEmpty(value)){
                        object.setPartStatus(value);
                    }

                    //gb18030 ,32 ,DataUtil.bytes2String(message[40])
                    object.setPartDesc(DataUtil.parse_part_desc(message, 41 + offset, 32));
                    object.setTimeLable(DataUtil.parse_time_stamp(message, 73 + offset, 6));
                    if(fireUploadData.getTimeLable().contains("000")){
                        fireUploadData.setTimeLable(object.getTimeLable());
                    }
                    fireUploadDataObojects.add(object);
                }

            } else if (DataFlag.getDataFlag(message) == DataFlag.DEV_OPT) {
                //设备操作信息,4\6
                for (int j = 0; j < size; j++) {
                    int offset = j * 10;
                    FireUploadDataOboject object = new FireUploadDataOboject();
                    object.setDeviceType(DataUtil.bytes2String(message[29 + offset]));
                    String value = AppDataUtil.device_type_map.get(object.getDeviceType());
                    if(!StringUtils.isEmpty(value)){
                        object.setDeviceType(value);
                    }
                    object.setDeviceAddress(DataUtil.bytes2String(message[30 + offset]));
                    object.setDeviceOptType(DataUtil.bytes2String(message[31 + offset]));
                    String value1 = AppDataUtil.device_part_opt_map.get(object.getDeviceOptType());
                    if(!StringUtils.isEmpty(value1)){
                        object.setDeviceOptType(value1);
                    }
                    object.setOpterNum(DataUtil.bytes2String(message[32 + offset]));
                    object.setTimeLable(DataUtil.parse_time_stamp(message, 33 + offset, 6));
                    if(fireUploadData.getTimeLable().contains("000")){
                        fireUploadData.setTimeLable(object.getTimeLable());
                    }
                    fireUploadDataObojects.add(object);
                }

            }
            fireUploadData.setFireUploadDataObojectList(fireUploadDataObojects);
        }

        //打印，发送消息队列
        ObjectMapper mapper = new ObjectMapper();
        try {
            String result = mapper.writeValueAsString(fireUploadData);
            //FireUploadDataServiceImpl fireUploadDataService = (FireUploadDataServiceImpl) SpringUtil.getBean("fireUploadDataServiceImpl");
            if (fireUploadData.getAppDataFlag().equals("2") || fireUploadData.getAppDataFlag().equals("4")) {
                log.info("插入数据 " + result);
                myServerHandler.fireUploadDataService.insertFireUploadData(fireUploadData);
            }else {
                log.info("心跳数据 " + result);
            }

        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

    }

    private void handlerMessagePlus(byte[] message) {
        //System.out.println("心跳信息");
        //String tenMessage = RS485Util.covertHex2Ten(HexEcodeUtil.ByteArrayToHexStr(message));
        String hexMessage = HexEcodeUtil.ByteArrayToHexStr(message);
        log.info(RS485Util.covertHex2Ten(hexMessage));
        FireUploadData fireUploadData = RS485Util.getFireUploadData(hexMessage);
        if (fireUploadData.getAppDataFlag().equals("2") || fireUploadData.getAppDataFlag().equals("4")) {
            ObjectMapper mapper = new ObjectMapper();
            String result = null;
            try {
                result = mapper.writeValueAsString(fireUploadData);
                log.info("上传数据： " + result);
                //mqttGateway.sendToMqtt(result, MQTTConfig.MQTT_TOPIC);

            } catch (JsonProcessingException e) {
                e.printStackTrace();

            }
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        //发送消息给客户端
        ctx.writeAndFlush(Unpooled.copiedBuffer("服务端已收到消息，并给你发送一个问号?", CharsetUtil.UTF_8));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //发生异常，关闭通道
        ctx.close();
    }


}
